home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sndintrf.c < prev    next >
C/C++ Source or Header  |  2000-05-23  |  20KB  |  942 lines

  1. #include "driver.h"
  2.  
  3.  
  4. /***************************************************************************
  5.  
  6.   Many games use a master-slave CPU setup. Typically, the main CPU writes
  7.   a command to some register, and then writes to another register to trigger
  8.   an interrupt on the slave CPU (the interrupt might also be triggered by
  9.   the first write). The slave CPU, notified by the interrupt, goes and reads
  10.   the command.
  11.  
  12. ***************************************************************************/
  13.  
  14. static int cleared_value = 0x00;
  15.  
  16. static int latch,read_debug;
  17.  
  18.  
  19. static void soundlatch_callback(int param)
  20. {
  21.     if (read_debug == 0 && latch != param)
  22.         logerror("Warning: sound latch written before being read. Previous: %02x, new: %02x\n",latch,param);
  23.     latch = param;
  24.     read_debug = 0;
  25. }
  26.  
  27. WRITE_HANDLER( soundlatch_w )
  28. {
  29.     /* make all the CPUs synchronize, and only AFTER that write the new command to the latch */
  30.     timer_set(TIME_NOW,data,soundlatch_callback);
  31. }
  32.  
  33. READ_HANDLER( soundlatch_r )
  34. {
  35.     read_debug = 1;
  36.     return latch;
  37. }
  38.  
  39. WRITE_HANDLER( soundlatch_clear_w )
  40. {
  41.     latch = cleared_value;
  42. }
  43.  
  44.  
  45. static int latch2,read_debug2;
  46.  
  47. static void soundlatch2_callback(int param)
  48. {
  49.     if (read_debug2 == 0 && latch2 != param)
  50.         logerror("Warning: sound latch 2 written before being read. Previous: %02x, new: %02x\n",latch2,param);
  51.     latch2 = param;
  52.     read_debug2 = 0;
  53. }
  54.  
  55. WRITE_HANDLER( soundlatch2_w )
  56. {
  57.     /* make all the CPUs synchronize, and only AFTER that write the new command to the latch */
  58.     timer_set(TIME_NOW,data,soundlatch2_callback);
  59. }
  60.  
  61. READ_HANDLER( soundlatch2_r )
  62. {
  63.     read_debug2 = 1;
  64.     return latch2;
  65. }
  66.  
  67. WRITE_HANDLER( soundlatch2_clear_w )
  68. {
  69.     latch2 = cleared_value;
  70. }
  71.  
  72.  
  73. static int latch3,read_debug3;
  74.  
  75. static void soundlatch3_callback(int param)
  76. {
  77.     if (read_debug3 == 0 && latch3 != param)
  78.         logerror("Warning: sound latch 3 written before being read. Previous: %02x, new: %02x\n",latch3,param);
  79.     latch3 = param;
  80.     read_debug3 = 0;
  81. }
  82.  
  83. WRITE_HANDLER( soundlatch3_w )
  84. {
  85.     /* make all the CPUs synchronize, and only AFTER that write the new command to the latch */
  86.     timer_set(TIME_NOW,data,soundlatch3_callback);
  87. }
  88.  
  89. READ_HANDLER( soundlatch3_r )
  90. {
  91.     read_debug3 = 1;
  92.     return latch3;
  93. }
  94.  
  95. WRITE_HANDLER( soundlatch3_clear_w )
  96. {
  97.     latch3 = cleared_value;
  98. }
  99.  
  100.  
  101. static int latch4,read_debug4;
  102.  
  103. static void soundlatch4_callback(int param)
  104. {
  105.     if (read_debug4 == 0 && latch4 != param)
  106.         logerror("Warning: sound latch 4 written before being read. Previous: %02x, new: %02x\n",latch2,param);
  107.     latch4 = param;
  108.     read_debug4 = 0;
  109. }
  110.  
  111. WRITE_HANDLER( soundlatch4_w )
  112. {
  113.     /* make all the CPUs synchronize, and only AFTER that write the new command to the latch */
  114.     timer_set(TIME_NOW,data,soundlatch4_callback);
  115. }
  116.  
  117. READ_HANDLER( soundlatch4_r )
  118. {
  119.     read_debug4 = 1;
  120.     return latch4;
  121. }
  122.  
  123. WRITE_HANDLER( soundlatch4_clear_w )
  124. {
  125.     latch4 = cleared_value;
  126. }
  127.  
  128.  
  129. void soundlatch_setclearedvalue(int value)
  130. {
  131.     cleared_value = value;
  132. }
  133.  
  134.  
  135.  
  136.  
  137.  
  138. /***************************************************************************
  139.  
  140.  
  141.  
  142. ***************************************************************************/
  143.  
  144. static void *sound_update_timer;
  145. static double refresh_period;
  146. static double refresh_period_inv;
  147.  
  148.  
  149. struct snd_interface
  150. {
  151.     unsigned sound_num;                                        /* ID */
  152.     const char *name;                                        /* description */
  153.     int (*chips_num)(const struct MachineSound *msound);    /* returns number of chips if applicable */
  154.     int (*chips_clock)(const struct MachineSound *msound);    /* returns chips clock if applicable */
  155.     int (*start)(const struct MachineSound *msound);        /* starts sound emulation */
  156.     void (*stop)(void);                                        /* stops sound emulation */
  157.     void (*update)(void);                                    /* updates emulation once per frame if necessary */
  158.     void (*reset)(void);                                    /* resets sound emulation */
  159. };
  160.  
  161.  
  162. #if (HAS_CUSTOM)
  163. static const struct CustomSound_interface *cust_intf;
  164.  
  165. int custom_sh_start(const struct MachineSound *msound)
  166. {
  167.     cust_intf = msound->sound_interface;
  168.  
  169.     if (cust_intf->sh_start)
  170.         return (*cust_intf->sh_start)(msound);
  171.     else return 0;
  172. }
  173. void custom_sh_stop(void)
  174. {
  175.     if (cust_intf->sh_stop) (*cust_intf->sh_stop)();
  176. }
  177. void custom_sh_update(void)
  178. {
  179.     if (cust_intf->sh_update) (*cust_intf->sh_update)();
  180. }
  181. #endif
  182. #if (HAS_DAC)
  183. int DAC_num(const struct MachineSound *msound) { return ((struct DACinterface*)msound->sound_interface)->num; }
  184. #endif
  185. #if (HAS_ADPCM)
  186. int ADPCM_num(const struct MachineSound *msound) { return ((struct ADPCMinterface*)msound->sound_interface)->num; }
  187. #endif
  188. #if (HAS_OKIM6295)
  189. int OKIM6295_num(const struct MachineSound *msound) { return ((struct OKIM6295interface*)msound->sound_interface)->num; }
  190. int OKIM6295_clock(const struct MachineSound *msound) { return ((struct OKIM6295interface*)msound->sound_interface)->frequency[0]; }
  191. #endif
  192. #if (HAS_MSM5205)
  193. int MSM5205_num(const struct MachineSound *msound) { return ((struct MSM5205interface*)msound->sound_interface)->num; }
  194. #endif
  195. #if (HAS_HC55516)
  196. int HC55516_num(const struct MachineSound *msound) { return ((struct hc55516_interface*)msound->sound_interface)->num; }
  197. #endif
  198. #if (HAS_K007232)
  199. int K007232_num(const struct MachineSound *msound) { return ((struct K007232_interface*)msound->sound_interface)->num_chips; }
  200. #endif
  201. #if (HAS_AY8910)
  202. int AY8910_clock(const struct MachineSound *msound) { return ((struct AY8910interface*)msound->sound_interface)->baseclock; }
  203. int AY8910_num(const struct MachineSound *msound) { return ((struct AY8910interface*)msound->sound_interface)->num; }
  204. #endif
  205. #if (HAS_YM2203)
  206. int YM2203_clock(const struct MachineSound *msound) { return ((struct YM2203interface*)msound->sound_interface)->baseclock; }
  207. int YM2203_num(const struct MachineSound *msound) { return ((struct YM2203interface*)msound->sound_interface)->num; }
  208. #endif
  209. #if (HAS_YM2413)
  210. int YM2413_clock(const struct MachineSound *msound) { return ((struct YM2413interface*)msound->sound_interface)->baseclock; }
  211. int YM2413_num(const struct MachineSound *msound) { return ((struct YM2413interface*)msound->sound_interface)->num; }
  212. #endif
  213. #if (HAS_YM2608)
  214. int YM2608_clock(const struct MachineSound *msound) { return ((struct YM2608interface*)msound->sound_interface)->baseclock; }
  215. int YM2608_num(const struct MachineSound *msound) { return ((struct YM2608interface*)msound->sound_interface)->num; }
  216. #endif
  217. #if (HAS_YM2610)
  218. int YM2610_clock(const struct MachineSound *msound) { return ((struct YM2610interface*)msound->sound_interface)->baseclock; }
  219. int YM2610_num(const struct MachineSound *msound) { return ((struct YM2610interface*)msound->sound_interface)->num; }
  220. #endif
  221. #if (HAS_YM2612)
  222. int YM2612_clock(const struct MachineSound *msound) { return ((struct YM2612interface*)msound->sound_interface)->baseclock; }
  223. int YM2612_num(const struct MachineSound *msound) { return ((struct YM2612interface*)msound->sound_interface)->num; }
  224. #endif
  225. #if (HAS_POKEY)
  226. int POKEY_clock(const struct MachineSound *msound) { return ((struct POKEYinterface*)msound->sound_interface)->baseclock; }
  227. int POKEY_num(const struct MachineSound *msound) { return ((struct POKEYinterface*)msound->sound_interface)->num; }
  228. #endif
  229. #if (HAS_TIA)
  230. int TIA_clock(const struct MachineSound *msound) { return ((struct TIAinterface*)msound->sound_interface)->baseclock; }
  231. #endif
  232. #if (HAS_YM3812)
  233. int YM3812_clock(const struct MachineSound *msound) { return ((struct YM3812interface*)msound->sound_interface)->baseclock; }
  234. int YM3812_num(const struct MachineSound *msound) { return ((struct YM3812interface*)msound->sound_interface)->num; }
  235. #endif
  236. #if (HAS_VLM5030)
  237. int VLM5030_clock(const struct MachineSound *msound) { return ((struct VLM5030interface*)msound->sound_interface)->baseclock; }
  238. #endif
  239. #if (HAS_TMS36XX)
  240. int TMS36XX_num(const struct MachineSound *msound) { return ((struct TMS36XXinterface*)msound->sound_interface)->num; }
  241. #endif
  242. #if (HAS_TMS5220)
  243. int TMS5220_clock(const struct MachineSound *msound) { return ((struct TMS5220interface*)msound->sound_interface)->baseclock; }
  244. #endif
  245. #if (HAS_YM2151 || HAS_YM2151_ALT)
  246. int YM2151_clock(const struct MachineSound *msound) { return ((struct YM2151interface*)msound->sound_interface)->baseclock; }
  247. int YM2151_num(const struct MachineSound *msound) { return ((struct YM2151interface*)msound->sound_interface)->num; }
  248. #endif
  249. #if (HAS_NES)
  250. int NES_num(const struct MachineSound *msound) { return ((struct NESinterface*)msound->sound_interface)->num; }
  251. #endif
  252. #if (HAS_SN76477)
  253. int SN76477_num(const struct MachineSound *msound) { return ((struct SN76477interface*)msound->sound_interface)->num; }
  254. #endif
  255. #if (HAS_SN76496)
  256. int SN76496_clock(const struct MachineSound *msound) { return ((struct SN76496interface*)msound->sound_interface)->baseclock[0]; }
  257. int SN76496_num(const struct MachineSound *msound) { return ((struct SN76496interface*)msound->sound_interface)->num; }
  258. #endif
  259. #if (HAS_MSM5205)
  260. int MSM5205_clock(const struct MachineSound *msound) { return ((struct MSM5205interface*)msound->sound_interface)->baseclock; }
  261. #endif
  262. #if (HAS_UPD7759)
  263. int UPD7759_clock(const struct MachineSound *msound) { return ((struct UPD7759_interface*)msound->sound_interface)->clock_rate; }
  264. #endif
  265. #if (HAS_ASTROCADE)
  266. int ASTROCADE_clock(const struct MachineSound *msound) { return ((struct astrocade_interface*)msound->sound_interface)->baseclock; }
  267. int ASTROCADE_num(const struct MachineSound *msound) { return ((struct astrocade_interface*)msound->sound_interface)->num; }
  268. #endif
  269. #if (HAS_K051649)
  270. int K051649_clock(const struct MachineSound *msound) { return ((struct k051649_interface*)msound->sound_interface)->master_clock; }
  271. #endif
  272. #if (HAS_K053260)
  273. int K053260_clock(const struct MachineSound *msound) { return ((struct K053260_interface*)msound->sound_interface)->clock; }
  274. #endif
  275. #if (HAS_CEM3394)
  276. int cem3394_num(const struct MachineSound *msound) { return ((struct cem3394_interface*)msound->sound_interface)->numchips; }
  277. #endif
  278. #if (HAS_QSOUND)
  279. int qsound_clock(const struct MachineSound *msound) { return ((struct QSound_interface*)msound->sound_interface)->clock; }
  280. #endif
  281. #if (HAS_SPEAKER)
  282. int speaker_num(const struct MachineSound *msound) { return ((struct Speaker_interface*)msound->sound_interface)->num; }
  283. #endif
  284. #if (HAS_WAVE)
  285. int wave_num(const struct MachineSound *msound) { return ((struct Wave_interface*)msound->sound_interface)->num; }
  286. #endif
  287.  
  288. struct snd_interface sndintf[] =
  289. {
  290.     {
  291.         SOUND_DUMMY,
  292.         "",
  293.         0,
  294.         0,
  295.         0,
  296.         0,
  297.         0,
  298.         0
  299.     },
  300. #if (HAS_CUSTOM)
  301.     {
  302.         SOUND_CUSTOM,
  303.         "Custom",
  304.         0,
  305.         0,
  306.         custom_sh_start,
  307.         custom_sh_stop,
  308.         custom_sh_update,
  309.         0
  310.     },
  311. #endif
  312. #if (HAS_SAMPLES)
  313.     {
  314.         SOUND_SAMPLES,
  315.         "Samples",
  316.         0,
  317.         0,
  318.         samples_sh_start,
  319.         0,
  320.         0,
  321.         0
  322.     },
  323. #endif
  324. #if (HAS_DAC)
  325.     {
  326.         SOUND_DAC,
  327.         "DAC",
  328.         DAC_num,
  329.         0,
  330.         DAC_sh_start,
  331.         0,
  332.         0,
  333.         0
  334.     },
  335. #endif
  336. #if (HAS_AY8910)
  337.     {
  338.         SOUND_AY8910,
  339.         "AY-8910",
  340.         AY8910_num,
  341.         AY8910_clock,
  342.         AY8910_sh_start,
  343.         0,
  344.         0,
  345.         0
  346.     },
  347. #endif
  348. #if (HAS_YM2203)
  349.     {
  350.         SOUND_YM2203,
  351.         "YM-2203",
  352.         YM2203_num,
  353.         YM2203_clock,
  354.         YM2203_sh_start,
  355.         YM2203_sh_stop,
  356.         0,
  357.         YM2203_sh_reset
  358.     },
  359. #endif
  360. #if (HAS_YM2151 || HAS_YM2151_ALT)
  361.     {
  362.         SOUND_YM2151,
  363.         "YM-2151",
  364.         YM2151_num,
  365.         YM2151_clock,
  366.         YM2151_sh_start,
  367.         YM2151_sh_stop,
  368.         0,
  369.         YM2151_sh_reset
  370.     },
  371. #endif
  372. #if (HAS_YM2608)
  373.     {
  374.         SOUND_YM2608,
  375.         "YM-2608",
  376.         YM2608_num,
  377.         YM2608_clock,
  378.         YM2608_sh_start,
  379.         YM2608_sh_stop,
  380.         0,
  381.         YM2608_sh_reset
  382.     },
  383. #endif
  384. #if (HAS_YM2610)
  385.     {
  386.         SOUND_YM2610,
  387.         "YM-2610",
  388.         YM2610_num,
  389.         YM2610_clock,
  390.         YM2610_sh_start,
  391.         YM2610_sh_stop,
  392.         0,
  393.         YM2610_sh_reset
  394.     },
  395. #endif
  396. #if (HAS_YM2610B)
  397.     {
  398.         SOUND_YM2610B,
  399.         "YM-2610B",
  400.         YM2610_num,
  401.         YM2610_clock,
  402.         YM2610B_sh_start,
  403.         YM2610_sh_stop,
  404.         0,
  405.         YM2610_sh_reset
  406.     },
  407. #endif
  408. #if (HAS_YM2612)
  409.     {
  410.         SOUND_YM2612,
  411.         "YM-2612",
  412.         YM2612_num,
  413.         YM2612_clock,
  414.         YM2612_sh_start,
  415.         YM2612_sh_stop,
  416.         0,
  417.         YM2612_sh_reset
  418.     },
  419. #endif
  420. #if (HAS_YM3438)
  421.     {
  422.         SOUND_YM3438,
  423.         "YM-3438",
  424.         YM2612_num,
  425.         YM2612_clock,
  426.         YM2612_sh_start,
  427.         YM2612_sh_stop,
  428.         0,
  429.         YM2612_sh_reset
  430.     },
  431. #endif
  432. #if (HAS_YM2413)
  433.     {
  434.         SOUND_YM2413,
  435.         "YM-2413",
  436.         YM2413_num,
  437.         YM2413_clock,
  438.         YM2413_sh_start,
  439.         YM2413_sh_stop,
  440.         0,
  441.         0
  442.     },
  443. #endif
  444. #if (HAS_YM3812)
  445.     {
  446.         SOUND_YM3812,
  447.         "YM-3812",
  448.         YM3812_num,
  449.         YM3812_clock,
  450.         YM3812_sh_start,
  451.         YM3812_sh_stop,
  452.         0,
  453.         0
  454.     },
  455. #endif
  456. #if (HAS_YM3526)
  457.     {
  458.         SOUND_YM3526,
  459.         "YM-3526",
  460.         YM3812_num,
  461.         YM3812_clock,
  462.         YM3812_sh_start,
  463.         YM3812_sh_stop,
  464.         0,
  465.         0
  466.     },
  467. #endif
  468. #if (HAS_Y8950)
  469.     {
  470.         SOUND_Y8950,
  471.         "Y8950",    /* (MSX-AUDIO) */
  472.         YM3812_num,
  473.         YM3812_clock,
  474.         Y8950_sh_start,
  475.         Y8950_sh_stop,
  476.         0,
  477.         0
  478.     },
  479. #endif
  480. #if (HAS_SN76477)
  481.     {
  482.         SOUND_SN76477,
  483.         "SN76477",
  484.         SN76477_num,
  485.         0,
  486.         SN76477_sh_start,
  487.         SN76477_sh_stop,
  488.         0,
  489.         0
  490.     },
  491. #endif
  492. #if (HAS_SN76496)
  493.     {
  494.         SOUND_SN76496,
  495.         "SN76496",
  496.         SN76496_num,
  497.         SN76496_clock,
  498.         SN76496_sh_start,
  499.         0,
  500.         0
  501.     },
  502. #endif
  503. #if (HAS_POKEY)
  504.     {
  505.         SOUND_POKEY,
  506.         "Pokey",
  507.         POKEY_num,
  508.         POKEY_clock,
  509.         pokey_sh_start,
  510.         pokey_sh_stop,
  511.         0,
  512.         0
  513.     },
  514. #endif
  515. #if (HAS_TIA)
  516.     {
  517.         SOUND_TIA,
  518.         "TIA",
  519.         0,
  520.         TIA_clock,
  521.         tia_sh_start,
  522.         tia_sh_stop,
  523.         tia_sh_update,
  524.         0
  525.     },
  526. #endif
  527. #if (HAS_NES)
  528.     {
  529.         SOUND_NES,
  530.         "Nintendo",
  531.         NES_num,
  532.         0,
  533.         NESPSG_sh_start,
  534.         NESPSG_sh_stop,
  535.         NESPSG_sh_update,
  536.         0
  537.     },
  538. #endif
  539. #if (HAS_ASTROCADE)
  540.     {
  541.         SOUND_ASTROCADE,
  542.         "Astrocade",
  543.         ASTROCADE_num,
  544.         ASTROCADE_clock,
  545.         astrocade_sh_start,
  546.         astrocade_sh_stop,
  547.         astrocade_sh_update,
  548.         0
  549.     },
  550. #endif
  551. #if (HAS_NAMCO)
  552.     {
  553.         SOUND_NAMCO,
  554.         "Namco",
  555.         0,
  556.         0,
  557.         namco_sh_start,
  558.         namco_sh_stop,
  559.         0,
  560.         0
  561.     },
  562. #endif
  563. #if (HAS_TMS36XX)
  564.     {
  565.         SOUND_TMS36XX,
  566.         "TMS36XX",
  567.         TMS36XX_num,
  568.         0,
  569.         tms36xx_sh_start,
  570.         tms36xx_sh_stop,
  571.         tms36xx_sh_update,
  572.         0
  573.     },
  574. #endif
  575. #if (HAS_TMS5220)
  576.     {
  577.         SOUND_TMS5220,
  578.         "TMS5520",
  579.         0,
  580.         TMS5220_clock,
  581.         tms5220_sh_start,
  582.         tms5220_sh_stop,
  583.         tms5220_sh_update,
  584.         0
  585.     },
  586. #endif
  587. #if (HAS_VLM5030)
  588.     {
  589.         SOUND_VLM5030,
  590.         "VLM5030",
  591.         0,
  592.         VLM5030_clock,
  593.         VLM5030_sh_start,
  594.         VLM5030_sh_stop,
  595.         VLM5030_sh_update,
  596.         0
  597.     },
  598. #endif
  599. #if (HAS_ADPCM)
  600.     {
  601.         SOUND_ADPCM,
  602.         "ADPCM",
  603.         ADPCM_num,
  604.         0,
  605.         ADPCM_sh_start,
  606.         ADPCM_sh_stop,
  607.         ADPCM_sh_update,
  608.         0
  609.     },
  610. #endif
  611. #if (HAS_OKIM6295)
  612.     {
  613.         SOUND_OKIM6295,
  614.         "OKI6295",
  615.         OKIM6295_num,
  616.         OKIM6295_clock,
  617.         OKIM6295_sh_start,
  618.         OKIM6295_sh_stop,
  619.         OKIM6295_sh_update,
  620.         0
  621.     },
  622. #endif
  623. #if (HAS_MSM5205)
  624.     {
  625.         SOUND_MSM5205,
  626.         "MSM5205",
  627.         MSM5205_num,
  628.         MSM5205_clock,
  629.         MSM5205_sh_start,
  630.         0,
  631.         0,
  632.         MSM5205_sh_reset,
  633.     },
  634. #endif
  635. #if (HAS_UPD7759)
  636.     {
  637.         SOUND_UPD7759,
  638.         "uPD7759",
  639.         0,
  640.         UPD7759_clock,
  641.         UPD7759_sh_start,
  642.         UPD7759_sh_stop,
  643.         0,
  644.         0
  645.     },
  646. #endif
  647. #if (HAS_HC55516)
  648.     {
  649.         SOUND_HC55516,
  650.         "HC55516",
  651.         HC55516_num,
  652.         0,
  653.         hc55516_sh_start,
  654.         0,
  655.         0,
  656.         0
  657.     },
  658. #endif
  659. #if (HAS_K005289)
  660.     {
  661.         SOUND_K005289,
  662.         "005289",
  663.         0,
  664.         0,
  665.         K005289_sh_start,
  666.         K005289_sh_stop,
  667.         0,
  668.         0
  669.     },
  670. #endif
  671. #if (HAS_K007232)
  672.     {
  673.         SOUND_K007232,
  674.         "007232",
  675.         K007232_num,
  676.         0,
  677.         K007232_sh_start,
  678.         0,
  679.         0,
  680.         0
  681.     },
  682. #endif
  683. #if (HAS_K051649)
  684.     {
  685.         SOUND_K051649,
  686.         "051649",
  687.         0,
  688.         K051649_clock,
  689.         K051649_sh_start,
  690.         K051649_sh_stop,
  691.         0,
  692.         0
  693.     },
  694. #endif
  695. #if (HAS_K053260)
  696.     {
  697.         SOUND_K053260,
  698.         "053260",
  699.         0,
  700.         K053260_clock,
  701.         K053260_sh_start,
  702.         K053260_sh_stop,
  703.         0,
  704.         0
  705.     },
  706. #endif
  707. #if (HAS_SEGAPCM)
  708.     {
  709.         SOUND_SEGAPCM,
  710.         "Sega PCM",
  711.         0,
  712.         0,
  713.         SEGAPCM_sh_start,
  714.         SEGAPCM_sh_stop,
  715.         SEGAPCM_sh_update,
  716.         0
  717.     },
  718. #endif
  719. #if (HAS_RF5C68)
  720.     {
  721.         SOUND_RF5C68,
  722.         "RF5C68",
  723.         0,
  724.         0,
  725.         RF5C68_sh_start,
  726.         RF5C68_sh_stop,
  727.         0,
  728.         0
  729.     },
  730. #endif
  731. #if (HAS_CEM3394)
  732.     {
  733.         SOUND_CEM3394,
  734.         "CEM3394",
  735.         cem3394_num,
  736.         0,
  737.         cem3394_sh_start,
  738.         cem3394_sh_stop,
  739.         0,
  740.         0
  741.     },
  742. #endif
  743. #if (HAS_C140)
  744.     {
  745.         SOUND_C140,
  746.         "C140",
  747.         0,
  748.         0,
  749.         C140_sh_start,
  750.         C140_sh_stop,
  751.         0,
  752.         0
  753.     },
  754. #endif
  755. #if (HAS_QSOUND)
  756.     {
  757.         SOUND_QSOUND,
  758.         "QSound",
  759.         0,
  760.         qsound_clock,
  761.         qsound_sh_start,
  762.         qsound_sh_stop,
  763.         0,
  764.         0
  765.     },
  766. #endif
  767. #if (HAS_SPEAKER)
  768.     {
  769.         SOUND_SPEAKER,
  770.         "Speaker",
  771.         speaker_num,
  772.         0,
  773.         speaker_sh_start,
  774.         speaker_sh_stop,
  775.         speaker_sh_update,
  776.         0
  777.     },
  778. #endif
  779. #if (HAS_WAVE)
  780.     {
  781.         SOUND_WAVE,
  782.         "Cassette",
  783.         wave_num,
  784.         0,
  785.         wave_sh_start,
  786.         wave_sh_stop,
  787.         wave_sh_update,
  788.         0
  789.     },
  790. #endif
  791. };
  792.  
  793.  
  794.  
  795. int sound_start(void)
  796. {
  797.     int totalsound = 0;
  798.     int i;
  799.  
  800.     /* Verify the order of entries in the sndintf[] array */
  801.     for (i = 0;i < SOUND_COUNT;i++)
  802.     {
  803.         if (sndintf[i].sound_num != i)
  804.         {
  805. logerror("Sound #%d wrong ID %d: check enum SOUND_... in src/sndintrf.h!\n",i,sndintf[i].sound_num);
  806.             return 1;
  807.         }
  808.     }
  809.  
  810.  
  811.     /* samples will be read later if needed */
  812.     Machine->samples = 0;
  813.  
  814.     refresh_period = TIME_IN_HZ(Machine->drv->frames_per_second);
  815.     refresh_period_inv = 1.0 / refresh_period;
  816.     sound_update_timer = timer_set(TIME_NEVER,0,NULL);
  817.  
  818.     if (mixer_sh_start() != 0)
  819.         return 1;
  820.  
  821.     if (streams_sh_start() != 0)
  822.         return 1;
  823.  
  824.     while (Machine->drv->sound[totalsound].sound_type != 0 && totalsound < MAX_SOUND)
  825.     {
  826.         if ((*sndintf[Machine->drv->sound[totalsound].sound_type].start)(&Machine->drv->sound[totalsound]) != 0)
  827.             goto getout;
  828.  
  829.         totalsound++;
  830.     }
  831.  
  832.     return 0;
  833.  
  834.  
  835. getout:
  836.     /* TODO: should also free the resources allocated before */
  837.     return 1;
  838. }
  839.  
  840.  
  841.  
  842. void sound_stop(void)
  843. {
  844.     int totalsound = 0;
  845.  
  846.  
  847.     while (Machine->drv->sound[totalsound].sound_type != 0 && totalsound < MAX_SOUND)
  848.     {
  849.         if (sndintf[Machine->drv->sound[totalsound].sound_type].stop)
  850.             (*sndintf[Machine->drv->sound[totalsound].sound_type].stop)();
  851.  
  852.         totalsound++;
  853.     }
  854.  
  855.     streams_sh_stop();
  856.     mixer_sh_stop();
  857.  
  858.     if (sound_update_timer)
  859.     {
  860.         timer_remove(sound_update_timer);
  861.         sound_update_timer = 0;
  862.     }
  863.  
  864.     /* free audio samples */
  865.     freesamples(Machine->samples);
  866.     Machine->samples = 0;
  867. }
  868.  
  869.  
  870.  
  871. void sound_update(void)
  872. {
  873.     int totalsound = 0;
  874.  
  875.  
  876.     profiler_mark(PROFILER_SOUND);
  877.  
  878.     while (Machine->drv->sound[totalsound].sound_type != 0 && totalsound < MAX_SOUND)
  879.     {
  880.         if (sndintf[Machine->drv->sound[totalsound].sound_type].update)
  881.             (*sndintf[Machine->drv->sound[totalsound].sound_type].update)();
  882.  
  883.         totalsound++;
  884.     }
  885.  
  886.     streams_sh_update();
  887.     mixer_sh_update();
  888.  
  889.     timer_reset(sound_update_timer,TIME_NEVER);
  890.  
  891.     profiler_mark(PROFILER_END);
  892. }
  893.  
  894.  
  895. void sound_reset(void)
  896. {
  897.     int totalsound = 0;
  898.  
  899.  
  900.     while (Machine->drv->sound[totalsound].sound_type != 0 && totalsound < MAX_SOUND)
  901.     {
  902.         if (sndintf[Machine->drv->sound[totalsound].sound_type].reset)
  903.             (*sndintf[Machine->drv->sound[totalsound].sound_type].reset)();
  904.  
  905.         totalsound++;
  906.     }
  907. }
  908.  
  909.  
  910.  
  911. const char *sound_name(const struct MachineSound *msound)
  912. {
  913.     if (msound->sound_type < SOUND_COUNT)
  914.         return sndintf[msound->sound_type].name;
  915.     else
  916.         return "";
  917. }
  918.  
  919. int sound_num(const struct MachineSound *msound)
  920. {
  921.     if (msound->sound_type < SOUND_COUNT && sndintf[msound->sound_type].chips_num)
  922.         return (*sndintf[msound->sound_type].chips_num)(msound);
  923.     else
  924.         return 0;
  925. }
  926.  
  927. int sound_clock(const struct MachineSound *msound)
  928. {
  929.     if (msound->sound_type < SOUND_COUNT && sndintf[msound->sound_type].chips_clock)
  930.         return (*sndintf[msound->sound_type].chips_clock)(msound);
  931.     else
  932.         return 0;
  933. }
  934.  
  935.  
  936. int sound_scalebufferpos(int value)
  937. {
  938.     int result = (int)((double)value * timer_timeelapsed (sound_update_timer) * refresh_period_inv);
  939.     if (value >= 0) return (result < value) ? result : value;
  940.     else return (result > value) ? result : value;
  941. }
  942.